import json
import jsonpath
import requests
import semver

# 导入BOM,获取项目编号
with open(r'D:\Project\NPM\express@1.0.8.json', encoding='utf-8-sig') as f:
    t = json.load(f)
    a_name = jsonpath.jsonpath(t, '$..name')
    a_version = jsonpath.jsonpath(t, '$..version')
    print(a_name, "\n", a_version)
    f.close()

# 循环输出package.json的所有漏洞项目及范围

# post参数
url = 'https://api.github.com/graphql'
api_token = "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"
headers = {'Authorization': 'token %s' % api_token}

list1 = []
for i in a_name:
    json1 = {
        "query": "query { securityVulnerabilities(ecosystem: NPM, first: 50, package: \"%s\", orderBy: {field: UPDATED_AT,direction:DESC}){nodes{advisory{databaseId}package{name}vulnerableVersionRange}totalCount}}" % (
            i)}
    r = requests.post(url=url, json=json1, headers=headers)
    if (r.status_code == 200):
        list1.append(r)
        print(r.text)

print('load_complete')
# response对象转str，并第一次清洗，去掉空值
list2 = []
s = "{\"data\":{\"securityVulnerabilities\":{\"nodes\":[],\"totalCount\":0}}}"  # 注意！！！这个字符串要随查询值进行更改的！
for i in list1:
    i2 = i.text
    if (i2 != s):
        list2.append(i2)

# str转字典
list3 = []
for i in list2:
    list3.append(json.loads(i))

#第二次清洗数据，解除多层嵌套，并去掉版本间的逗号
y = {}
for i in list3:
    x = {}
    for j in i['data']['securityVulnerabilities']['nodes']:
        b_id = j['advisory']['databaseId']
        b_name = j['package']['name']
        b_range = j['vulnerableVersionRange']
        if b_id in x.keys():
            x[b_id] = x[b_id] + "||" + b_range
        else:
            x[b_id] = b_range
        #print (x[b_id])
        #for i in x[b_id]:
        x[b_id] = x[b_id].replace(',','')
        #print (x[b_id])
    y.update({b_name: x})
    #print (x['924'])
print (y)

#判断当前包是否在受影响范围内，并输出受影响的包
z = {}
for n,v in zip(a_name,a_version):
    if n in y.keys():
        #print (n,v)
        for i in y[n]:
            #print (i,y[n][i])
            #print (semver.satisfies(v,y[n][i]))
            #s1 = y[n][i].replace(',','')
            #print (y[n][i].replace(',',''))
            if ((semver.satisfies(v,y[n][i])) == True):
                #semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3')
                #print (i)
                z.setdefault(n,[]).append(i)
print (z)
